package com.example.icampusevent;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.example.icampusevent.jsonobjects.ReturnStatus;
import com.example.icampusevent.jsonobjects.TimeQueryEvent;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.readystatesoftware.viewbadger.BadgeView;

import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.app.ActionBar;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.Toast;


public class MainActivity extends MapActivity {
	
	private final int RANGEQUERY = 0;
	private final int KNNQUERY = 1;
	private int queryMode;
	
	private MapView campusMapView = null;
	private List<Overlay> mapOverlays = null;
	private CircleOverlay circleOverlay = null;
	private Drawable drawable = null;
	private MapTag tags = null;
	
	private LocationManager locationManager = null;
	private String locationProvider = null;
	
	private String userId = null;
	private Long eventId = null;
	private ArrayList<TimeQueryEvent> eventList = null;
	private Handler handler = null;
	private final int UPDATE = 0;
	
	private BadgeView badge;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        
        // set up mapview
        campusMapView = (MapView)findViewById(R.id.main_map_view);
        mapOverlays = campusMapView.getOverlays();
        drawable = this.getResources().getDrawable(R.drawable.map_marker);
        tags = new MapTag(drawable, this);
        
        Button msgButton = (Button)findViewById(R.id.go_message_button);
	    badge = new BadgeView(MainActivity.this, msgButton);
    }
    
    
    @Override
    public void onResume() {
    	super.onResume();
    	
    	Intent intent = getIntent();
        userId = intent.getStringExtra("USERID");
    	
    	// Setup list view
        ListView listView=(ListView)findViewById(R.id.list);
        listView.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> listView, View v, int position, long id) {
				Intent intent = new Intent(MainActivity.this, EventDetailActivity.class);
				intent.putExtra("EVENTID", eventList.get(position).getId());
				intent.putExtra("USERID", userId);
				intent.putExtra("MODE", 0);
				startActivity(intent);
			}
        });
        
        // Setup the handler
        this.handler = new Handler() {
        	@Override
        	public void handleMessage(Message msg) {
        		if(msg.what == UPDATE) {
        			ListView listView=(ListView)findViewById(R.id.list);
        			Adapter adapter=new EventListAdapter(MainActivity.this, eventList);
       		     	listView.setAdapter((ListAdapter) adapter);
       		     	addEventMarker();
        		}
        	}
        };
        
        // Set OnclickListeners for buttons
        setButtons();
        
    	setNotification();
    	
    	// set up defualt view
        queryMode = RANGEQUERY;
        setViewForRangeQuery();
    }
    
    
    @Override 
    public void onNewIntent(Intent newIntent) {
    	setIntent(newIntent);
    }
    
    
    private void setButtons() {
    	
    	// set up customized action bar
    	Button homeButton = (Button)findViewById(R.id.go_home_button);
    	homeButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// check the check in event
			}
    	});
    	
    	
    	Button searchButton = (Button)findViewById(R.id.go_search_button);
    	searchButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// start the search activity
	    		Intent searchIntent = new Intent(MainActivity.this, SearchActivity.class);
	    		searchIntent.putExtra("USERID", userId);
	    		startActivity(searchIntent);
			}
    	});
    	
    	Button friendButton = (Button)findViewById(R.id.go_friend_button);
    	friendButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// start friend viewing activity
				Intent friendIntent = new Intent(MainActivity.this, FriendActivity.class);
	    		friendIntent.putExtra("USERID", userId);
	    		startActivity(friendIntent);
			}
    	});
    	
    	Button messageButton = (Button)findViewById(R.id.go_message_button);
    	messageButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				Intent msgIntent = new Intent(MainActivity.this, MessageActivity.class);
	    		msgIntent.putExtra("USERID", userId);
	    		startActivity(msgIntent);
			}
    	});
    	
    	ImageButton goOutButton = (ImageButton)findViewById(R.id.go_out_button);
    	goOutButton.setOnClickListener(new OnClickListener() {
    		public void onClick(View v) {
    			// show popup menu
    			PopupMenu popupMenu = new PopupMenu(MainActivity.this, v);
    		    popupMenu.getMenuInflater().inflate(R.menu.activity_main, popupMenu.getMenu());
    		    
    		    popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
					public boolean onMenuItemClick(MenuItem item) {
						switch (item.getItemId()) {
						
				        case R.id.sign_out_popitem:
				        	File dir = getFilesDir();
				    		File file = new File(dir, "USERID");
				    		if(file.exists()) {
				    			file.delete();
				    		}
				    		Intent loginIntent = new Intent(MainActivity.this, LoginActivity.class);
							startActivity(loginIntent);
				            return true;
				            
				        case R.id.check_out_popitem:
				        	String url = "http://hamedaan.usc.edu:8080/team15/AlertServlet?q=current&userid=" + userId;
				        	GetCheckinEventTask task = new GetCheckinEventTask();
				        	task.execute(url);
				            return true;
				            
				        default:
				            return false;
				            
						}
					}
    		    });
    		    
    		    popupMenu.show();
    		}
    	});
    	
    	// set up query buttons
    	Button rangeButton = (Button)findViewById(R.id.select_range_button);
        rangeButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(queryMode != RANGEQUERY) {
					queryMode = RANGEQUERY;
					setViewForRangeQuery();
				}
			}
        });
        
        Button knnButton = (Button)findViewById(R.id.find_nearest_button);
        knnButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(queryMode != KNNQUERY) {
					queryMode = KNNQUERY;
					setViewForKnnQuery();
				}
			}
        });
    }
    
    
    private void setNotification() {
    	String url = "http://hamedaan.usc.edu:8080/team15/AlertServlet?q=count&userid=" + this.userId;
    	GetMessageNumberTask task = new GetMessageNumberTask();
    	task.execute(url);
    }
    
    
    private void setViewForRangeQuery() {
        // Initialize mapview
    	MapController controller = campusMapView.getController();
        GeoPoint centerPoint = new GeoPoint((int)(34.0215650330 * 1E6), (int)(-118.2866058350 * 1E6));
        controller.setCenter(centerPoint);
        controller.animateTo(centerPoint);
        controller.setZoom(18); 
        circleOverlay = new CircleOverlay(this, 34.0215650330, -118.2866058350, 400);
        mapOverlays.clear();
        mapOverlays.add(circleOverlay);
        
        // Populate event list
    	String url = "http://hamedaan.usc.edu:8080/team15/GeoServlet?q=range&lat=34.0215650330&lng=-118.2866058350&radius=" + (400 * 0.85);
        LoadEventListTask task = new LoadEventListTask();
        task.execute(url);
    }
    
    
    private void setViewForKnnQuery() {
    	double lat = 34.0215650330;
    	double lng = -118.2866058350;
    	
    	// Get user's current location
    	Location currentLocation = getCurrentLocation();
    	if(currentLocation == null) {
    		toast("Error: cannot get your current location.");
    	}
    	else {
    		lat = currentLocation.getLatitude();
    		lng = currentLocation.getLongitude();
    	}
    	
    	// Populate event list
    	String url = "http://hamedaan.usc.edu:8080/team15/GeoServlet?q=knn&lat=" 
    	             + lat + "&lng=" + lng + "&k=6";
        LoadEventListTask task = new LoadEventListTask();
        task.execute(url);
        
        // Initialize mapview
        MapController controller = campusMapView.getController();
        GeoPoint centerPoint = new GeoPoint((int)(34.0215650330 * 1E6), (int)(-118.2866058350 * 1E6));
        controller.setCenter(centerPoint);
        controller.animateTo(centerPoint);
        controller.setZoom(18); 
    }

    
    private void addEventMarker() {
        mapOverlays.clear();
        tags.clearTags();
        for(TimeQueryEvent event : eventList) {
        	GeoPoint point = new GeoPoint((int)(event.getLat() * 1E6), 
            		(int)(event.getLng() * 1E6));
            OverlayItem srcItem = new OverlayItem(point, "Hello!", "Have Fun!");
            tags.addTag(srcItem);
            tags.addEventId(event.getId());
        }
        mapOverlays.add(tags);
        if(queryMode == RANGEQUERY) {
        	mapOverlays.add(circleOverlay);
        }
        
        campusMapView.invalidate();
    }
    
    
    private Location getCurrentLocation() {
    	locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
	    Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
	    if(location != null)
	    	return location;
	    else 
	    	return null;
	}
    
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.action_bar_menu, menu);
        return true;
    }
    

	@Override
	protected boolean isRouteDisplayed() {
		return true;
	}
	
	
	private class GetCheckinEventTask extends AsyncTask<String, Integer, Reader> {
	     protected Reader doInBackground(String... url) {
	    	 InputStream source = retrieveStream(url[0]);
	 		 if(source == null) return null;
	 		 
	 		 Reader inputReader = new InputStreamReader(source);
	 		 return inputReader;
	     }

	     protected void onPostExecute(Reader json) {
	 		 Gson gson = new Gson();
	 		 ListView listView=(ListView)findViewById(R.id.list);
			 ReturnStatus status = gson.fromJson(json, ReturnStatus.class);
			 if(status.getStatus().equals("-1")) {
				 toast("You haven't Checked in any event.");
			 }
			 else {
				 eventId = Long.parseLong(status.getStatus());
				 Intent detailIntent = new Intent(MainActivity.this, EventDetailActivity.class);
				 detailIntent.putExtra("EVENTID", eventId);
		    	 detailIntent.putExtra("USERID", userId);
		    	 detailIntent.putExtra("MODE", 1);
		    	 startActivity(detailIntent);
			 }
	     }
	     
	    // Get data stream from server
	 	private InputStream retrieveStream(String url) {
	 		DefaultHttpClient client = new DefaultHttpClient();
	 		HttpGet request = new HttpGet(url);
	 		try {
	 			HttpResponse response = client.execute(request);
	 			final int status = response.getStatusLine().getStatusCode();
	 			if(status != HttpStatus.SC_OK) {
	 				toast("ERROR CODE: " + status + " for URL " + url);
	 				return null;
	 			}
	 			HttpEntity responseEntity = response.getEntity();
	 			return responseEntity.getContent();
	 		}
	 		catch(IOException e) {
	 			request.abort();
	 			toast("ERROR for " + url);
	 		}
	 		
	 		return null;
	 	}
	}
	
	
	private class GetMessageNumberTask extends AsyncTask<String, Integer, Reader> {
	     protected Reader doInBackground(String... url) {
	    	 InputStream source = retrieveStream(url[0]);
	 		 if(source == null) return null;
	 		 
	 		 Reader inputReader = new InputStreamReader(source);
	 		 return inputReader;
	     }

	     protected void onPostExecute(Reader json) {
	 		 Gson gson = new Gson();
	 		 ListView listView=(ListView)findViewById(R.id.list);
			 ReturnStatus status = gson.fromJson(json, ReturnStatus.class);

			 int num = Integer.parseInt(status.getStatus());
			 if(num == -1) {
				 toast("Error: cannot get messages number.");
			 }
			 else if(num == 0) {
				 badge.hide();
			 }
			 else {
			     badge.setText(Integer.toString(num));
			     badge.setBadgePosition(BadgeView.POSITION_TOP_RIGHT);
			     badge.show();
			 }
			 
	     }
	     
	    // Get data stream from server
	 	private InputStream retrieveStream(String url) {
	 		DefaultHttpClient client = new DefaultHttpClient();
	 		HttpGet request = new HttpGet(url);
	 		try {
	 			HttpResponse response = client.execute(request);
	 			final int status = response.getStatusLine().getStatusCode();
	 			if(status != HttpStatus.SC_OK) {
	 				toast("ERROR CODE: " + status + " for URL " + url);
	 				return null;
	 			}
	 			HttpEntity responseEntity = response.getEntity();
	 			return responseEntity.getContent();
	 		}
	 		catch(IOException e) {
	 			request.abort();
	 			toast("ERROR for " + url);
	 		}
	 		
	 		return null;
	 	}
	}
	
	
	private class LoadEventListTask extends AsyncTask<String, Integer, Reader> {
	     protected Reader doInBackground(String... url) {
	    	 InputStream source = retrieveStream(url[0]);
	 		 if(source == null) return null;
	 		 
	 		 Reader inputReader = new InputStreamReader(source);
	 		 return inputReader;
	     }

	     protected void onPostExecute(Reader json) {
	    	 Type listType = new TypeToken<ArrayList<TimeQueryEvent>>(){}.getType();
	 		 Gson gson = new Gson();
	 		 ListView listView=(ListView)findViewById(R.id.list);
			 eventList = gson.fromJson(json, listType);
			 Adapter adapter=new EventListAdapter(MainActivity.this, eventList);
		     listView.setAdapter((ListAdapter) adapter);
		     addEventMarker();
	     }
	     
	    // Get data stream from server
	 	private InputStream retrieveStream(String url) {
	 		DefaultHttpClient client = new DefaultHttpClient();
	 		HttpGet request = new HttpGet(url);
	 		try {
	 			HttpResponse response = client.execute(request);
	 			final int status = response.getStatusLine().getStatusCode();
	 			if(status != HttpStatus.SC_OK) {
	 				toast("ERROR CODE: " + status + " for URL " + url);
	 				return null;
	 			}
	 			HttpEntity responseEntity = response.getEntity();
	 			return responseEntity.getContent();
	 		}
	 		catch(IOException e) {
	 			request.abort();
	 			toast("ERROR for " + url);
	 		}
	 		
	 		return null;
	 	}
	}
	
	
	public void setEventList(ArrayList<TimeQueryEvent> list) {
		eventList = list;
	}
	
	
	public Handler getHandler() {
		return this.handler;
	}
	
	public String getUserId() {
		return this.userId;
	}
	
	
	public void toast(String s) {
		CharSequence text = s;
		int duration = Toast.LENGTH_LONG;
		Toast toast = Toast.makeText(this, text, duration);
		toast.show();
	}
}



